/******************************************************************************/
/* File: main.cpp                                                             */
/******************************************************************************/

#include <getopt.h>
#include <stdlib.h>
#include "socketClass.h"
#include "ctrlSocket.h"
#include "dataStore.h"
#define VERSION 0.1

void PrintVersion() {
    std::cout << "fGenor version " << VERSION << std::endl;
}

void PrintUsage() {
    
    std::cout << "Usage: fGenor [-s|-c host] [options]" << std::endl;
    std::cout << "       fGenor [-h|--help] [-v|--version]" << std::endl;
    
    std::cout << "\nOptions: " << std::endl;
    std::cout << "    -p, --port           server port to listen on / connect to" << std::endl;
    std::cout << "    -c, --client <host>  run in client mode, connecting to <host>" << std::endl;
    std::cout << "    -s, --server         run in server mode" << std::endl;
    std::cout << "    -b, --bind   <host>  bind to specific interface" << std::endl;
    std::cout << "    -f, --file   <file>  server read config from this file" << std::endl;
    std::cout << "    -6, --ipv6           only use ipv6" << std::endl;
    std::cout << "    -v, --version        show version information and quit" << std::endl;
    std::cout << "    -h, --help           show help message and quit" << std::endl;
}

int ParseArguments(Arguments *pa, int argc, char **argv) {
    
    static struct option longopts[] = {
        {"port", required_argument, NULL, 'p'},
        {"client", required_argument, NULL, 'c'},
        {"server", no_argument, NULL, 's'},
        {"bind", required_argument, NULL, 'b'},
        {"file", required_argument, NULL, 'f'},
        {"ipv6", no_argument, NULL, '6'},
        {"version", no_argument, NULL, 'v'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}
    };
    
    int flag;
    
    while( (flag = getopt_long(argc, argv, "p:c:sb:f:6vh", longopts, NULL)) != -1 ) {
        switch (flag) {
            case ('p'):
                pa->iServerPort = atoi(optarg);
                break;
            case ('c'):
                pa->iRole = 1;
                pa->sServerIP = strdup(optarg);
                break;
            case ('s'):
                pa->iRole = 2;
                break;
            case ('b'):
                pa->sServerIP = strdup(optarg);
                break;
            case ('f'):
                pa->sFileName = strdup(optarg);
                break;
            case ('a'):
                pa->bUseIPv6 = true;
                break;
            case ('v'):
                PrintVersion();
                exit(1);
            case ('h'):
            default:
                PrintUsage();
                exit(1);
        }
    }

    return pa->iRole;
}

int main(int argc, char **argv) {
    
    Arguments *pa = new Arguments();
    int ret = ParseArguments(pa, argc, argv);

    if(ret == 1) {
        // Client
        IPAddress ipaddr;
        ipaddr.SetHostName(pa->sServerIP, pa->bUseIPv6);
        int port = pa->iServerPort;
        
        CtrlClient *pcc = new CtrlClient(ipaddr, port, pa->bUseIPv6);
        pcc->RunClient();

    } 
    else if(ret == 2) {
        // Server
        CtrlServerSetting *pCtrlServerSetting = new CtrlServerSetting();
        
        if(pa->sFileName == NULL) 
            pCtrlServerSetting->sFileName = strdup("./conf/flow.conf");
        else
            pCtrlServerSetting->sFileName = pa->sFileName;
        
        if(pa->sServerIP == NULL) 
            pCtrlServerSetting->sHostName = strdup("0.0.0.0");
        else
            pCtrlServerSetting->sHostName = pa->sServerIP;
        
        if(pa->iServerPort != -1)
            pCtrlServerSetting->iLocalPort = pa->iServerPort;
            
        pCtrlServerSetting->bUseIPv6 = pa->bUseIPv6;
        
        CtrlServer *pcs = new CtrlServer(pCtrlServerSetting);
        pcs->RunServer();
    }
    else {
        PrintUsage();
    }
    
    return 0;
}


/******************************************************************************/
/* End File: main.cpp                                                         */
/******************************************************************************/